package com.example.network;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.URL;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection;

import org.json.JSONArray;
import org.json.JSONObject;


public class NetworkHandler {

	private static final String ACCESS_KEY = "3f9a19b3-8564-41a6-a669-7685dea0272e";
	private static final String SECRET_KEY = "5ab15b4c-9b87-4fb8-93ca-9e3c9b767353";

	private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
	private static final char[] encodeMap = initEncodeMap();

	private static char[] initEncodeMap() {

		char[] map = new char[64];

		int i;

		for (i = 0; i < 26; i++)
			map[i] = (char) ('A' + i);

		for (i = 26; i < 52; i++)
			map[i] = (char) ('a' + (i - 26));

		for (i = 52; i < 62; i++)
			map[i] = (char) ('0' + (i - 52));

		map[62] = '+';

		map[63] = '/';

		return map;

	}

	public static String getSignature(String data, String key) throws Exception {

		// get an hmac_sha1 key from the raw key bytes
		SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(),
				HMAC_SHA1_ALGORITHM);

		// get an hmac_sha1 Mac instance and initialize with the signing key
		Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
		mac.init(signingKey);

		// compute the hmac on input data bytes
		byte[] rawHmac = mac.doFinal(data.getBytes());

		return bytArrayToHex(rawHmac);
	}

	private static String bytArrayToHex(byte[] a) {
		StringBuilder sb = new StringBuilder();
		for (byte b : a)
			sb.append(String.format("%02x", b & 0xff));
		return sb.toString();
	}

	public static final String LOGIN = "login";
	private static NetworkHandler instance;

	private NetworkHandler() {

	}

	public static NetworkHandler instance() {
		if (instance == null) {
			instance = new NetworkHandler();
		}
		return instance;
	}

	public void getAccountInfo() {

		String tonce = "" + (System.currentTimeMillis() * 1000);

		String params = "tonce=" + tonce.toString() + "&accesskey="
				+ ACCESS_KEY
				+ "&requestmethod=post&id=1&method=getAccountInfo&params=";

		String hash;
		try {
			hash = getSignature(params, SECRET_KEY);
			String url = "https://api.btcchina.com/api_trade_v1.php";
			URL obj = new URL(url);
			HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
			String userpass = ACCESS_KEY + ":" + hash;
			String basicAuth = "Basic "
					+ printBase64Binary(userpass.getBytes());

			// add reuqest header
			con.setRequestMethod("POST");
			con.setRequestProperty("Json-Rpc-Tonce", tonce.toString());
			 con.setRequestProperty ("Authorization", basicAuth);
			String postdata = "{\"method\": \"getAccountInfo\", \"params\": [], \"id\": 1}";

			// Send post request
			con.setDoOutput(true);
			DataOutputStream wr = new DataOutputStream(con.getOutputStream());
			wr.writeBytes(postdata);
			wr.flush();
			wr.close();

			int responseCode = con.getResponseCode();
			System.out.println("\nSending 'POST' request to URL : " + url);
			System.out.println("Post parameters : " + postdata);
			System.out.println("Response Code : " + responseCode);

			BufferedReader in = new BufferedReader(new InputStreamReader(
					con.getInputStream()));
			String inputLine;
			StringBuffer response = new StringBuffer();

			while ((inputLine = in.readLine()) != null) {
				response.append(inputLine);
			}
			in.close();

			// print result
			System.out.println(response.toString());

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	
	public String getReponseFor(String what, JSONArray para){
		String response = null; 
		try {
			String tonce = "" + (System.currentTimeMillis() * 1000);

			String params = "tonce=" + tonce.toString() + "&accesskey="
					+ ACCESS_KEY
					+ "&requestmethod=post&id=1&method="+what+"&params=";
			for(int i=0; i<para.length(); i++){
				params +=para.get(i);
				if(i!=para.length()-1){
					params += ",";
				}
			}
			String hash;
			hash = getSignature(params, SECRET_KEY);
			String url = "https://api.btcchina.com/api_trade_v1.php";
			URL obj = new URL(url);
			HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
			String userpass = ACCESS_KEY + ":" + hash;
			String basicAuth = "Basic "
					+ printBase64Binary(userpass.getBytes());

			// add reuqest header
			con.setRequestMethod("POST");
			con.setRequestProperty("Json-Rpc-Tonce", tonce.toString());
			 con.setRequestProperty ("Authorization", basicAuth);
			 JSONObject jso = new JSONObject();
			 jso.put("method", what);
			 jso.put("params", para);
			 jso.put("id", 1);
			 String postdata = jso.toString();
//			String postdata = "{\"method\": \"" + what + "\", \"params\": [\""+para+"\"], \"id\": 1}";
         
			// Send post request
			con.setDoOutput(true);
			DataOutputStream wr = new DataOutputStream(con.getOutputStream());
			wr.writeBytes(postdata);
			wr.flush();
			wr.close();

			int responseCode = con.getResponseCode();
			System.out.println("\nSending 'POST' request to URL : " + url);
			System.out.println("Post parameters : " + postdata);
			System.out.println("Response Code : " + responseCode);

			BufferedReader in = new BufferedReader(new InputStreamReader(
					con.getInputStream()));
			String inputLine;
			StringBuffer responsebuffer = new StringBuffer();

			while ((inputLine = in.readLine()) != null) {
				responsebuffer.append(inputLine);
			}
			in.close();
            response = responsebuffer.toString();
			// print result
			System.out.println(responsebuffer.toString());

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return response;
	}
	

	public static String _printBase64Binary(byte[] input) {

		return _printBase64Binary(input, 0, input.length);

	}

	public static String _printBase64Binary(byte[] input, int offset, int len) {

		char[] buf = new char[((len + 2) / 3) * 4];

		int ptr = _printBase64Binary(input, offset, len, buf, 0);

		assert ptr == buf.length;

		return new String(buf);

	}

	public static int _printBase64Binary(byte[] input, int offset, int len,
			char[] buf, int ptr) {

		for (int i = offset; i < len; i += 3) {

			switch (len - i) {

			case 1:

				buf[ptr++] = encode(input[i] >> 2);

				buf[ptr++] = encode(((input[i]) & 0x3) << 4);

				buf[ptr++] = '=';

				buf[ptr++] = '=';

				break;

			case 2:

				buf[ptr++] = encode(input[i] >> 2);

				buf[ptr++] = encode(

				((input[i] & 0x3) << 4) |

				((input[i + 1] >> 4) & 0xF));

				buf[ptr++] = encode((input[i + 1] & 0xF) << 2);

				buf[ptr++] = '=';

				break;

			default:

				buf[ptr++] = encode(input[i] >> 2);

				buf[ptr++] = encode(

				((input[i] & 0x3) << 4) |

				((input[i + 1] >> 4) & 0xF));

				buf[ptr++] = encode(

				((input[i + 1] & 0xF) << 2) |

				((input[i + 2] >> 6) & 0x3));

				buf[ptr++] = encode(input[i + 2] & 0x3F);

				break;

			}

		}

		return ptr;

	}

	public static int _printBase64Binary(byte[] input, int offset, int len,
			byte[] out, int ptr) {

		byte[] buf = out;

		int max = len + offset;

		for (int i = offset; i < max; i += 3) {

			switch (max - i) {

			case 1:

				buf[ptr++] = encodeByte(input[i] >> 2);

				buf[ptr++] = encodeByte(((input[i]) & 0x3) << 4);

				buf[ptr++] = '=';

				buf[ptr++] = '=';

				break;

			case 2:

				buf[ptr++] = encodeByte(input[i] >> 2);

				buf[ptr++] = encodeByte(

				((input[i] & 0x3) << 4) |

				((input[i + 1] >> 4) & 0xF));

				buf[ptr++] = encodeByte((input[i + 1] & 0xF) << 2);

				buf[ptr++] = '=';

				break;

			default:

				buf[ptr++] = encodeByte(input[i] >> 2);

				buf[ptr++] = encodeByte(

				((input[i] & 0x3) << 4) |

				((input[i + 1] >> 4) & 0xF));

				buf[ptr++] = encodeByte(

				((input[i + 1] & 0xF) << 2) |

				((input[i + 2] >> 6) & 0x3));

				buf[ptr++] = encodeByte(input[i + 2] & 0x3F);

				break;

			}

		}

		return ptr;

	}

	public String printBase64Binary(byte[] val) {

		return _printBase64Binary(val);

	}

	public static char encode(int i) {

		return encodeMap[i & 0x3F];

	}

	public static byte encodeByte(int i) {

		return (byte) encodeMap[i & 0x3F];

	}

}
